package com.hcc.cpwxdemo.controller;

import com.alibaba.fastjson.JSONObject;
import com.hcc.cpwxdemo.biz.QyWxAppBiz;
import com.hcc.cpwxdemo.config.WxCpConfiguration;
import com.hcc.cpwxdemo.dto.QyWxAppDTO;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author hcc
 */
@Slf4j
@RestController
public class WxPortalResController {

    @Autowired
    private QyWxAppBiz qyWxAppBiz;

    /**
     * @param agentId   应用id
     * @param corpId    企业id
     * @param signature 签名
     * @param timestamp 时间戳
     * @param nonce     nonce
     * @param echostr   带解密的密文
     * @return
     */
    @GetMapping(value = "/wx/cp/portal/{corpId}/{agentId}", produces = "text/plain;charset=utf-8")
    public String authGet(Integer agentId, String corpId, String signature, String timestamp, String nonce, String echostr) {
        log.info("\n接收到来自微信服务器的认证消息：signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]",
                signature, timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        //获取 微信企业应用配置信息
        QyWxAppDTO qyWxAppDTO = qyWxAppBiz.getDtoByCorpIdAndAgentId(corpId, agentId);
        if (qyWxAppDTO == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        final WxCpService wxCpService = WxCpConfiguration.getCpService(corpId, agentId);
        if (wxCpService == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {
            return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr);
        }
        return "非法请求";
    }


    /**
     * @param agentId     agentId
     * @param corpId      corpId
     * @param requestBody requestBody
     * @param signature   signature
     * @param timestamp   timestamp
     * @param nonce       nonce
     * @return
     */
    @PostMapping(value = "/wx/cp/portal/{corpId}/{agentId}", produces = "application/xml; charset=UTF-8")
    public String post(Integer agentId, String corpId, String requestBody, String signature, String timestamp, String nonce) {
        log.info("\n接收微信请求：[signature=[{}], timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                signature, timestamp, nonce, requestBody);

        QyWxAppDTO qyWxAppDTO = qyWxAppBiz.getDtoByCorpIdAndAgentId(corpId, agentId);
        if (qyWxAppDTO == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        final WxCpService wxCpService = WxCpConfiguration.getCpService(corpId, agentId);
        if (wxCpService == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }

        WxCpXmlMessage inMessage = WxCpXmlMessage.fromEncryptedXml(requestBody, wxCpService.getWxCpConfigStorage(),
                timestamp, nonce, signature);
        log.debug("\n消息解密后内容为：\n{} ", JSONObject.toJSONString(inMessage));
        log.info("get cpWx event push. msgType={}, eventType={}, changeType={}", inMessage.getMsgType(), inMessage.getEvent(), inMessage.getChangeType());
        // 接收企业微信消息 处理
        WxCpXmlOutMessage outMessage = this.route(corpId, agentId, inMessage);
        if (outMessage == null) {
            return "";
        }

        String out = outMessage.toEncryptedXml(wxCpService.getWxCpConfigStorage());
        log.debug("\n组装回复信息：{}", out);
        return out;
    }

    private WxCpXmlOutMessage route(String corpId, Integer agentId, WxCpXmlMessage message) {
        try {
            return WxCpConfiguration.getRouters().get(corpId + agentId).route(message);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return null;
    }
}
